(function(global){
	if(!String.prototype.format){
		String.prototype.format = function() {
			var args = Array.prototype.slice.call(arguments);
			return this.replace(/\{(\d+)\}/g, 
				function(m, i){
					return args[i];
				});
		};
	}

	var Yo = {};
	global.Yo = Yo;
})(this);

(function(Yo){
	// localstorage
	var Storage = function(){
		this.storage = window.localStorage;
		if(!this.storage)
			console.log('Web local storage api not support!');
	};

	var extend = {
		clear: function(){
			if(!this.storage)
				return;

			this.storage.clear();
		}, 

		get: function(key){
			if(!this.storage)
				return;

			var str = this.storage[key];
			if(!str || 'undefined' == str || 'null' == str)
				return null;

			return JSON.parse(str);
		}, 

		set: function(key, val){
			if(!this.storage)
				return;

			this.storage[key] = JSON.stringify(val);
		},
			
		remove: function(key){
			if(!this.storage)
				return;

			this.storage.removeItem(key);
		}
	};

	for(key in extend){
		Storage.prototype[key] = extend[key];
	}
	Yo.Storage = Storage;
})(this.Yo);

(function(Yo){
	var Utils = {};

	// cookie helper
	Utils.getCookie = function(cookieName){
		var cookieStart = document.cookie.indexOf(cookieName);
		var cookieEnd = document.cookie.indexOf(";", cookieStart);
		return cookieStart == -1 ? '' : unescape(document.cookie.substring(cookieStart + cookieName.length + 1, (cookieEnd > cookieStart ? cookieEnd : document.cookie.length)));
	};

	Utils.setCookie = function(cookieName, cookieValue, seconds, path, domain, secure) {
		var expires = new Date();
		expires.setTime(expires.getTime() + seconds);
		document.cookie = escape(cookieName) + '=' + escape(cookieValue)
			+ (expires ? '; expires=' + expires.toGMTString() : '')
			+ (path ? '; path=' + path : '/')
			+ (domain ? '; domain=' + domain : '')
			+ (secure ? '; secure' : '');
	};

	// query parameters
	Utils.params = function(url){
		url = url || document.location.href;
		var data = {};
		var pos = url.indexOf('?');
		if(pos != -1){
			var query = url.substring(pos);
			if(query){
				var ll = query.substring(1).split('&');
				var i = 0;
				for(; i < ll.length; i++){
					var arr = ll[i].split('=');
					if(arr.length == 2)
						data[arr[0]] = decodeURI(arr[1]);
				}
			}
		}
		return data;
	};

	Utils.alert = function(msg){
		alert(msg);
	};

	Yo.Utils = Utils;
})(this.Yo);

(function(Yo){
	var Pager = function(pageNum, pageSize, totalCount){
		this.pageNum = pageNum;
		this.pageSize = pageSize;
		this.totalCount = totalCount;
	};
	Pager.prototype.getStart = function(){
		return (this.pageNum - 1) * this.pageSize;
	};
	Pager.prototype.getEnd = function(){
		return this.pageNum * this.pageSize;
	};
	Pager.prototype.hasPre = function(){
		return this.pageNum > 1;
	};
	Pager.prototype.hasNext = function(){
		return this.pageNum * this.pageSize < this.totalCount;
	};
	Pager.prototype.getTotalPageNum = function(){
		var num = Math.floor(this.totalCount / this.pageSize);
		if(this.totalCount % this.pageSize != 0)
			num++;

		return num;
	};

	Yo.Pager = Pager;
})(this.Yo);

(function(Yo){
	var Storage = Yo.Storage;

	var Conf = {};
	Conf.get = function(key){
		var storage = new Storage();
		return storage.get(key);
	};
	Conf.set = function(key, val){
		var storage = new Storage();
		storage.set(key, val);
	};
	Conf.remove = function(key){
		var storage = new Storage();
		storage.remove(key);
	};
	Yo.Conf = Conf;
})(this.Yo);

(function(Yo){
	var Utils = Yo.Utils;
	var Conf = Yo.Conf;

	var User = {
		KEY: 'userLogin',
		COOKIE_KEY: 'ibid-user-login'
	};
	User.getFromCookie = function(){
		var str = Utils.getCookie(this.COOKIE_KEY);
		if(!str)
			return null;

		return JSON.parse(JSON.parse(str));
	};
	User.get = function(){
		return Conf.get(this.KEY);
	};
	User.set = function(val){
		Conf.set(this.KEY, val);
	};
	User.remove = function(){
		Utils.setCookie(this.COOKIE_KEY, '');
		Conf.remove(this.KEY);
	};
	Yo.User = User;
})(this.Yo);

(function(Yo){
	var Section = {
		handlers: {},
		interceptors: [],

		addInter: function(pat, fn){
			this.interceptors.push({pat: pat, fn: fn});
		}, 

		addPageFn: function(page, fn){
			this.handlers[page] = fn;
		}
	};
	Section.show = function(page){
		$('#' + page).addClass('active');
	};
	Section.hide = function(page){
		$('#' + page).removeClass('active');
	};

	Section.go = function(page, force){
		if(!force){
			var i = 0;
			for(; i < this.interceptors.length; i++){
				var it = this.interceptors[i];
				if(typeof it.pat == 'object' && it.pat.constructor == RegExp){
					if(page.match(it.pat)){
						var isOk = it.fn(page);
						if(!isOk)
							return;
					}
				}
			}
		}

		this.show(page);
		var fn = this.handlers[page];
		if(fn)
			fn();
	};

	Yo.Section = Section;
})(this.Yo);

(function(Yo){
	User = Yo.User;
	Section = Yo.Section;

	var Req = {};
	Req.get = function(url, params, cb){
		if(typeof params == 'function'){
			cb = params;
			params = {};
		}

		Pace.track(function(){
			$.get(url, params, function(data){
				if(data && data.error){
					if('session-invalid' == data.error){
						User.remove();
						Section.show('pageChangeUser');
						return;
					}else{
						alert(data.error);
					}
				}else{
					cb(data);
				}
			});
		});
	};
	Req.post = function(url, data, cb){
		Pace.track(function(){
			$.ajax({
				type: 'POST', 
				url: url, 
				data: JSON.stringify(data), 
				dataType: 'json', 
				contentType: 'application/json',
				success: function(data){
					if(data && data.error){
						if('session-invalid' == data.error){
							User.remove();
							Section.show('pageChangeUser');
							return;
						}else{
							alert(data.error);
						}
					}else{
						cb(data);
					}
				}, 
				error: function(xhr, errorType, error){
					console.error(error);
				}
			});
		});
	};

	Yo.Req = Req;
})(this.Yo);

$(function(){
	FastClick.attach(document.body);

	// add page change event
	$('[yo-href]').each(function(){
		var link = $(this);
		link.click(function(){
			var page = link.attr('yo-href');
			if(page.indexOf('#') == 0)
				page = page.substr(1);

			Yo.Section.go(page);
			return false;
		});
	});
});
